package com.xstudio.pvzreborn.recipe;

import com.xstudio.pvzreborn.PVZReborn;
import com.xstudio.pvzreborn.recipe.machine.SPCRecipe;
import com.xstudio.pvzreborn.recipe.machine.polarcraftingtable.PCTRecipeBase;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author superhelo
 */

public class RecipeManager {

	private static final Map<String, RecipeType<?>> RECIPE_TYPES = new HashMap<>();
	private static final Map<String, RecipeSerializer<?>> RECIPE_SERIALIZERS = new HashMap<>();

	public static void init(IEventBus bus) {
		PVZReborn.LOGGER.info("Initializing recipes");
		bus.addGenericListener(RecipeSerializer.class, RecipeManager::registerSerializerByEvent);

		registerSerializer(SPCRecipe.TYPE_ID, new SPCRecipe.Serializer());
		registerSerializer(PCTRecipeBase.TYPE_ID, new PCTRecipeBase.Serializer());
		PVZReborn.LOGGER.info("Initialized recipes");
	}

	public static void registerSerializerByEvent(RegistryEvent.Register<RecipeSerializer<?>> event) {
		RECIPE_SERIALIZERS.forEach((key, value) -> {
			ResourceLocation id = PVZReborn.prefix(key);
			value.setRegistryName(id);
			event.getRegistry().register(value);
			Registry.register(Registry.RECIPE_TYPE, id, RECIPE_TYPES.get(key));
		});
	}

	public static <T extends Recipe<?>> void registerSerializer(String name, RecipeSerializer<T> serializer) {
		RECIPE_SERIALIZERS.put(name, serializer);
		RECIPE_TYPES.put(name, new PVZRecipeType<T>());
	}

	@SuppressWarnings("unchecked")
	public static <T extends Recipe<?>> RecipeType<T> getRecipeType(String name) {
		return (RecipeType<T>) Registry.RECIPE_TYPE.get(PVZReborn.prefix(name));
	}

	@SuppressWarnings("unchecked")
	public static <T extends Recipe<?>> RecipeSerializer<T> getRecipeSerializer(String name) {
		return (RecipeSerializer<T>) RECIPE_SERIALIZERS.get(name);
	}

	public static <C extends Container, T extends Recipe<C>> List<T> getRecipes(Level level, RecipeType<T> recipeType) {
		return level.getRecipeManager().getAllRecipesFor(recipeType);
	}

	/**
	 * @param limitTags 是否将标签列入比较清单
	 * @author Bread_NiceCat
	 */
	public static <C extends Container, T extends Recipe<C>> List<T> getRecipesByOutput(Level level, RecipeType<T> recipeType, ItemStack output, boolean limitTags) {
		List<T> recipes = level.getRecipeManager().getAllRecipesFor(recipeType);
		recipes.removeIf(recipe -> !recipe.getResultItem().equals(output, limitTags));
		return recipes;
	}

	private static class PVZRecipeType<T extends Recipe<?>> implements RecipeType<T> {

		@Override
		public String toString() {
			return Registry.RECIPE_TYPE.getKey(this).toString();
		}

	}

}
